package edu.nctu.csie.jichang.database.save;

import java.io.File;
import java.util.List;

import org.apache.commons.lang.StringEscapeUtils;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;

import edu.nctu.csie.jichang.database.dbinfo.LoginInfo;
import edu.nctu.csie.jichang.database.model.cell.ColumnInfo;
import edu.nctu.csie.jichang.database.model.cell.DBDatabase;
import edu.nctu.csie.jichang.database.model.cell.DBRow;
import edu.nctu.csie.jichang.database.model.cell.DBSchema;
import edu.nctu.csie.jichang.database.model.cell.DBTable;
import edu.nctu.csie.jichang.database.model.datavalue.DBString;
import edu.nctu.csie.jichang.database.model.datavalue.DataValue;
import edu.nctu.csie.jichang.database.util.DBException;
import edu.nctu.csie.jichang.database.util.DateUtil;
import edu.nctu.csie.jichang.database.util.StringUtil;
import edu.nctu.csie.jichang.database.util.XMLUtil;

public class SaveXML implements ISave {

	public void doSave(List<LoginInfo> pConns, DBDatabase pDatabase)throws Exception {
		throw new DBException("no support save to database");
	}
	
	public static final String DBDatabase = "DBDatabase";
	public static final String DBSchema   = "DBSchema";
	public static final String DBTable    = "DBTable";
	public static final String DBHeader   = "DBHeader";
	public static final String DBROWS     = "DBRows";
	public static final String DBROW      = "DBRow";
	public static final String DBCell     = "DBCell";
	
	public void doSave(File pFile, DBDatabase pDatabase) throws Exception {
		Document tDoc = DocumentHelper.createDocument();
		Element tRoot = tDoc.addElement(DBDatabase);
		tRoot.addAttribute("time", DateUtil.getFullDate(DateUtil.getDate()));
		for (DBSchema s : pDatabase.getAllSchema()) {
			Element tSchema = tRoot.addElement(DBSchema);
			tSchema.addAttribute("name", s.getName());
			saveTable(s, tSchema);
		}
		XMLUtil.documentToFile(tDoc, pFile);
	}

	private void saveTable(DBSchema pDBSchema, Element pElement) {
		for (DBTable t : pDBSchema.getAllTables()) {
			if(t.getCount() > 0 ){
				Element tTable = pElement.addElement(DBTable);
				tTable.addAttribute("name", t.getName());
				tTable.addAttribute("count",StringUtil.getString(t.getCount()));
				saveHeader(t, tTable);
				saveRow(t, tTable);
			}else{
				pElement.addComment("table " +t.getName() + " without data");
			}
		}
	}

	private void saveHeader(DBTable pDBTable, Element pTable) {
		Element tHeader = pTable.addElement(DBHeader);
		for (String c : pDBTable.getTableHeader().getColumnNames()) {
			ColumnInfo tInfo = pDBTable.getTableHeader().getColumnType(c);
			Element tElement = tHeader.addElement("column");
			tElement.addAttribute("name", tInfo.getName());
			tElement.addAttribute("rawtype",StringUtil.getString(tInfo.getRawType()));
			tElement.addAttribute("type", tInfo.getColumnType().toString());
			tElement.addAttribute("nullable", StringUtil.getString(tInfo.isNullable()));
		}
	}

	private void saveRow(DBTable pDBTable, Element pTable) {
		Element tRows   = pTable.addElement(DBROWS);
		for (DBRow r : pDBTable.getAllRows()) {
			Element tRow = tRows.addElement(DBROW);
			tRow.addAttribute("token", r.getName());
			for (String c : r.getCellNames()) {
				if(r.getCell(c).getName() != null){
					Element tCell = tRow.addElement(DBCell);
					tCell.addAttribute("column",c);
					DataValue<?> tDataValue = r.getCell(c);
					String tValue = tDataValue.getName();
					if (tDataValue instanceof DBString) {
						tValue = StringEscapeUtils.escapeXml(tValue);
					}
					tCell.addText(tValue);
				}
			}
		}
	}
}
